<template>
  <div>
    <div style="border-bottom: 1px solid #ebeef5; margin: 2px;">
      <el-button-group>
        <el-tooltip :open-delay="500" content="新建根目录" placement="top">
          <el-button icon="el-icon-folder-add" size="mini" type="primary" @click="addCatalog(null)" />
        </el-tooltip>
        <el-tooltip :content="`新建${eTitle}`" :open-delay="500" placement="top">
          <el-button icon="el-icon-document-add" size="mini" type="primary" @click="addElement(0)" />
        </el-tooltip>
        <el-tooltip :open-delay="500" content="搜索" placement="top">
          <el-button size="mini" type="primary" @click="handleClickSearch"><svg-icon icon-class="search" /></el-button>
        </el-tooltip>
      </el-button-group>
    </div>
    <splitpanes style="height: 87vh">
      <pane :min-size="10" :size="30">
        <div style="width: 100%; height: 100%;">
          <div id="leftDiv" style="overflow-y: scroll; height: 100%;">
            <tree-component
              ref="treeComponent"
              :element-label="eTitle"
              catalog-label="目录"
              draggable
              lazy
              @tree-content="treeContent"
              @tree-sort="treeSort"
              @choose-catalog="chooseCatalog"
              @reload-catalog="reloadCatalog"
              @copy-catalog="copyCatalog"
              @add-catalog="addCatalog"
              @delete-catalog="deleteCatalog"
              @choose-element="chooseElement"
              @add-element="addElement"
              @delete-element="deleteElement"
              @copy-element="copyElement"
            />
          </div>
        </div>
      </pane>
      <pane :min-size="20" :size="70">
        <div id="rightDiv" style="overflow-y: scroll; width: 100%; height: 98%;">
          <el-tabs v-if="activeName" v-model="activeName" style="width: 100%;" type="border-card">
            <el-tab-pane v-if="activeName === 'catalog'" label="目录" name="catalog">
              <catalog-component
                ref="catalogComponent"
                :catalog-info="catalog"
                :type="eType"
                @create="createCatalog"
                @update="updateCatalog"
              />
            </el-tab-pane>
            <el-tab-pane v-if="activeName === 'element'" :label="eTitle" name="element">
              <div style="text-align: right">
                <el-button-group style="margin-top: 0px; margin-right: 12px; margin-bottom: 4px;">
                  <el-tooltip :open-delay="500" content="历史记录" placement="top">
                    <el-button :disabled="element.id===undefined" icon="el-icon-link" size="mini" type="info" @click="handleHistory" />
                  </el-tooltip>
                  <el-tooltip :open-delay="500" content="保存" placement="top">
                    <el-button icon-class="skill" size="mini" type="primary" @click="saveElement"><svg-icon icon-class="save" /></el-button>
                  </el-tooltip>
                </el-button-group>
              </div>
              <el-card shadow="hover">
                <el-alert close-text="Get!" show-icon style="margin-bottom: 10px" title="DataBase 定义，当需要执行数据库命令时直接选择对应名称的 DataBase 定义即可。" type="info">
                  <div>1、名称：起一个合理的名字更容易记住</div>
                  <div>2、数据库类型：需要连接的数据库类型</div>
                  <div v-if="element.extra1.databaseType === 'mysql'">
                    <div>3、URL：数据库连接字串，例：jdbc:mysql://localhost:3306/XXX?serverTimezone=GMT&useSSL=false&characterEncoding=UTF-8</div>
                    <div>4、用户名：数据库用户名</div>
                    <div>5、密码：数据库密码</div>
                  </div>
                  <div v-if="element.extra1.databaseType === 'redis'">
                    <div>3、HOST / IP：redis 的域名 或 IP</div>
                    <div>4、PORT：redis 的端口</div>
                    <div>5、DB：需要操作的库</div>
                    <div>6、密码：数据库密码</div>
                  </div>
                </el-alert>

                <!-- mysql -->
                <el-form v-if="element.extra1.databaseType === 'mysql'" ref="elementMysql" :model="element" :rules="rules" class="demo-table-expand" label-position="right" label-width="100px" size="small">
                  <el-form-item label="名称" prop="name">
                    <el-input v-model="element.name" placeholder="请输入名称" />
                  </el-form-item>
                  <el-form-item label="数据库类型" prop="extra1.databaseType">
                    <template>
                      <el-select v-model="element.extra1.databaseType" placeholder="请选择 数据库类型" style="width:100%" @change="onDatabaseTypeChange">
                        <el-option
                          v-for="item in databaseTypeOptions"
                          :key="item.value"
                          :disabled="item.disabled"
                          :label="item.label"
                          :value="item.value"
                        />
                      </el-select>
                    </template>
                  </el-form-item>
                  <el-form-item label="URL" prop="uri">
                    <el-input v-model="element.uri" placeholder="请输入 URL(数据库连接字串)，例：jdbc:mysql://localhost:3306/XXX?serverTimezone=GMT&useSSL=false&characterEncoding=UTF-8" />
                  </el-form-item>
                  <el-form-item label="用户名" prop="extra1.username">
                    <el-input v-model="element.extra1.username" placeholder="请输入数据库用户名" />
                  </el-form-item>
                  <el-form-item label="密码" prop="extra1.password">
                    <el-input v-model="element.extra1.password" placeholder="请输入数据库密码" />
                  </el-form-item>
                </el-form>

                <!-- redis -->
                <el-form v-if="element.extra1.databaseType === 'redis'" ref="elementRedis" :model="element" :rules="rules" class="demo-table-expand" label-position="right" label-width="100px" size="small">
                  <el-form-item label="名称" prop="name">
                    <el-input v-model="element.name" placeholder="请输入名称" />
                  </el-form-item>
                  <el-form-item label="数据库类型" prop="extra1.databaseType">
                    <template>
                      <el-select v-model="element.extra1.databaseType" placeholder="请选择 数据库类型" style="width:100%" @change="onDatabaseTypeChange">
                        <el-option
                          v-for="item in databaseTypeOptions"
                          :key="item.value"
                          :disabled="item.disabled"
                          :label="item.label"
                          :value="item.value"
                        />
                      </el-select>
                    </template>
                  </el-form-item>
                  <el-form-item label="HOST / IP" prop="uri">
                    <el-input v-model="element.uri" placeholder="请输入 HOST / IP" />
                  </el-form-item>
                  <el-form-item label="PORT" prop="extra1.port">
                    <el-input v-model="element.extra1.port" maxlength="5" placeholder="请输入 PORT" />
                  </el-form-item>
                  <el-form-item label="DB" prop="extra1.db">
                    <el-input v-model="element.extra1.db" maxlength="5" placeholder="请输入 PORT" />
                  </el-form-item>
                  <el-form-item label="密码">
                    <el-input v-model="element.extra1.password" placeholder="请输入数据库密码" />
                  </el-form-item>
                </el-form>
              </el-card>
            </el-tab-pane>
          </el-tabs>
        </div>
      </pane>
    </splitpanes>

    <el-dialog :visible.sync="searchDialogFormVisible" title="搜索" width="1200px" :close-on-click-modal="false">
      <interface-search-component
        ref="interfaceSearchComponent"
        :type="eType"
        @dblclickResultRow="dblclickResultRow"
      />
    </el-dialog>

    <el-dialog :visible.sync="historyDialogFormVisible" title="历史记录" width="1200px" :close-on-click-modal="false">
      <api-history-component
        ref="apiHistoryComponent"
        @dblclickResultRow="dblclickHistoryRow"
      />
    </el-dialog>
  </div>
</template>

<style>
.splitpanes__pane {
  justify-content: flex-start;
  align-items: flex-start;
  display: flex;
  border: 1px solid #ebeef5;
}
.splitpanes__splitter {
  width: 5px;
  margin-left: -1px
}
#leftDiv::-webkit-scrollbar, #rightDiv::-webkit-scrollbar {
  width: 0px;
}
</style>

<script>
import { Pane, Splitpanes } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'
import TreeComponent from '@/components/functional_test/Tree/index.vue'
import { validPositiveInteger, validPositiveNaturalNumber } from '@/utils/validate'
import CatalogComponent from '@/components/functional_test/Catalog/index.vue'
import InterfaceSearchComponent from '@/components/functional_test/Search/interfaceSearch.vue'
import { copy as catalogCopy, del as catalogDel, listTreeContent, treeSort } from '@/api/functional_test/catalog'
import {
  create as apiCreate,
  del as apiDel,
  selectById as apiSelectById,
  update as apiUpdate
} from '@/api/functional_test/test_data_manage/api'
import ApiHistoryComponent from '@/components/functional_test/History/apiHistory'

export default {
  components: { Splitpanes, Pane, TreeComponent, CatalogComponent, InterfaceSearchComponent, ApiHistoryComponent },
  filters: {
    statusFilter(status) {
      const statusMap = {
        published: 'success',
        draft: 'gray',
        deleted: 'danger'
      }
      return statusMap[status]
    }
  },
  data() {
    return {
      searchDialogFormVisible: false,
      eType: 14, // 元素类型
      eTitle: ' DataBase',
      activeName: null, // 当前激活的 tab 名称
      currentCatalogId: 0, // 当前选中的 catalog ID
      catalog: {}, // catalog 对象
      element: {}, // element 对象
      databaseTypeOptions: [
        {
          value: 'mysql',
          label: 'MySql'
        }, {
          value: 'oracle',
          label: 'Oracle',
          disabled: true
        }, {
          value: 'sqlite',
          label: 'SQLite',
          disabled: true
        }, {
          value: 'sqlserver',
          label: 'SQL Server',
          disabled: true
        }, {
          value: 'redis',
          label: 'Redis'
        }],
      historyDialogFormVisible: false, // 历史记录弹窗
      rules: {
        name: [
          { required: true, message: '名称不能为空', trigger: 'blur' },
          { max: 100, message: '名称长度不能超过 100 个字符', trigger: 'blur' }
        ],
        'extra1.databaseType': [
          { required: true, message: '请选择数据库类型', trigger: 'blur' }
        ],
        uri: [
          { required: true, message: '请输入 URL(数据库连接字串)', trigger: 'blur' },
          { max: 255, message: 'URL(数据库连接字串) 长度不能超过 255 个字符', trigger: 'blur' }
        ],
        'extra1.port': [
          { required: true, message: '请输入 PORT', trigger: 'blur' },
          { validator: validPositiveInteger, message: 'PORT 只能输入正整数', trigger: 'blur' }
        ],
        'extra1.db': [
          { required: true, message: '请输入 DB', trigger: 'blur' },
          { validator: validPositiveNaturalNumber, message: 'DB 只能输入自然数', trigger: 'blur' }
        ],
        'extra1.username': [
          { required: true, message: '请输入 用户名', trigger: 'blur' },
          { max: 50, message: '用户名 长度不能超过 50 个字符', trigger: 'blur' }
        ],
        'extra1.password': [
          { required: true, message: '请输入 密码', trigger: 'blur' },
          { max: 50, message: '密码 长度不能超过 50 个字符', trigger: 'blur' }
        ]
      }
    }
  },
  created() {
  },
  methods: {
    // 新增时初始化 element 数据
    resetElement() {
      this.element = {
        'projectId': this.$store.getters.projectId,
        'catalogId': this.currentCatalogId,
        'type': this.eType,
        'name': '',
        'url': '',
        'extra1': {
          'databaseType': 'mysql',
          'port': '',
          'db': '',
          'username': '',
          'password': ''
        }
      }
    },
    // 数据库类型改变
    onDatabaseTypeChange(value) {
      this.resetElement()
      if (value === 'mysql') { // mysql
        this.element.extra1.databaseType = value
        this.$nextTick(() => {
          this.$refs['elementMysql'].clearValidate()
        })
      } else if (value === 'redis') { // redis
        this.element.extra1.databaseType = value
        this.element.extra1.port = 6379
        this.element.extra1.db = 0
        this.$nextTick(() => {
          this.$refs['elementRedis'].clearValidate()
        })
      }
    },
    // 设置 element 数据（当服务端返回数据后有些类型不符需要在这个方法中转换）
    setElement(ele) {
      this.element = ele
      this.element.extra1 = JSON.parse(this.element.extra1)
    },
    // tree：装载当前树节点数据
    treeContent(parentId, resolve) {
      listTreeContent({
        projectId: this.$store.getters.projectId,
        type: this.eType,
        parentId: parentId
      }).then(response => {
        resolve(response.data)
      })
    },
    // tree：拖拽排序
    treeSort(draggingNode, dropNode, dropType) {
      treeSort(this.$store.getters.projectId, this.eType, draggingNode.data, dropNode.data, dropType).then(response => {
        this.$message({ message: '修改排序成功!', type: 'success' })
      })
    },
    // tree：点击一个分类后调用此方法
    chooseCatalog(id) {
      this.activeName = 'catalog' // 设置当前 tab catalog
      this.currentCatalogId = this.catalog.id
      this.$nextTick(() => {
        this.$refs.catalogComponent.loadData(id)
      })
    },
    // tree：点击刷新一个分类的按钮后回调此方法
    reloadCatalog() {
      this.activeName = null // 清除 tab activeName
    },
    // tree：点击复制一个分类后调此方法
    copyCatalog(id, resolve) {
      catalogCopy(this.eType, this.$store.getters.projectId, id).then(response => {
        resolve(response.data)
      })
    },
    // tree：点击添加一个分类后调此方法
    addCatalog(parent_id) {
      this.activeName = 'catalog' // 设置当前 tab catalog
      this.$nextTick(() => {
        this.$refs.catalogComponent.add(parent_id)
      })
    },
    // tree：点击复制一个元素后调此方法
    copyElement(parent_id, id) {
      this.currentCatalogId = parent_id
      this.activeName = 'element' // 设置当前 tab element
      this.$nextTick(() => {
        apiSelectById(this.eType, id).then(response => {
          response.data.id = undefined
          this.$nextTick(() => {
            this.setElement(response.data)
          })
        })
      })
    },
    // tree：http接口定义修改成功后回调此方法
    updateElement(elementInfo) {
      this.$refs.treeComponent.updateNode(elementInfo)
    },
    // tree：分类添加成功后回调此方法
    createCatalog(catalogInfo) {
      this.catalog = catalogInfo
      this.$refs.treeComponent.appendNode(catalogInfo.id, catalogInfo.parentId, catalogInfo.name, true, null, null)
    },
    // tree：分类修改成功后回调此方法
    updateCatalog(catalogInfo) {
      this.catalog = catalogInfo
      this.$refs.treeComponent.updateNode(catalogInfo)
    },
    // tree：删除一个分类
    deleteCatalog(id, resolve) {
      catalogDel(this.$store.getters.projectId, this.eType, id).then(response => {
        resolve()
        this.activeName = null // 清除 tab activeName
      })
    },
    // tree：点击一个元素后调用此方法
    chooseElement(id) {
      apiSelectById(this.eType, id).then(response => {
        this.activeName = 'element' // 设置当前 tab element
        this.setElement(response.data)
      })
    },
    // tree：点击添加一个元素后调此方法
    addElement(parent_id) {
      this.currentCatalogId = parent_id
      this.resetElement()
      this.activeName = 'element' // 设置当前 tab element
    },
    // 点击元素保存按钮调用此方法
    saveElement: function() {
      let e
      if (this.element.extra1.databaseType === 'mysql') {
        e = this.$refs['elementMysql']
      } else if (this.element.extra1.databaseType === 'redis') {
        e = this.$refs['elementRedis']
      }
      e.validate((valid) => {
        if (valid) {
          this.element.type = this.eType
          this.element.extra1 = JSON.stringify(this.element.extra1, null, 0)

          if (!this.element.id) { // 新增 element
            apiCreate(this.element).then(response => {
              this.setElement(response.data)
              this.$refs.treeComponent.appendNode(this.element.id, this.element.catalogId, this.element.name, 'false', null, null)
              this.$message({ message: '添加成功!', type: 'success' })
            })
          } else { // 修改 element
            apiUpdate(this.element).then(response => {
              this.setElement(response.data)
              this.$refs.treeComponent.updateNode(this.element)
              this.$message({ message: '保存成功!', type: 'success' })
            })
          }
        }
      })
    },
    // tree：删除一个元素
    deleteElement(id, resolve) {
      apiDel(this.eType, id).then(response => { // 这里要改成 delElement
        resolve()
        this.activeName = null // 清除 tab activeName
      })
    },
    // 单击搜索按钮
    handleClickSearch() {
      this.searchDialogFormVisible = true
    },
    // 双击搜索结果行
    dblclickResultRow(elementParent) {
      this.searchDialogFormVisible = false
      this.$refs.treeComponent.setCurrentNode(elementParent)
    },
    // 点击 history 按钮
    handleHistory() {
      this.historyDialogFormVisible = true
      this.$nextTick(() => {
        this.$refs.apiHistoryComponent.loadData(this.element.id)
      })
    },
    // 双击历史结果行
    dblclickHistoryRow(ele) {
      this.historyDialogFormVisible = false
      this.setElement(ele)
    }
  }
}
</script>
